package com.hyt.it.ogt.kq.service.bm.service.stcenter.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.DateUtils;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.kq.common.bm.enums.BmCostType;
import com.hyt.it.ogt.kq.common.bm.enums.BmMidOrderPayStatus;
import com.hyt.it.ogt.kq.common.bm.enums.BmPayBusinessFlowType;
import com.hyt.it.ogt.kq.common.bm.enums.BmPayStatusEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectNeedPayEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectVerifyEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmSubjectNeedPayEnum;
import com.hyt.it.ogt.kq.common.bm.enums.pay.PayProviderType;
import com.hyt.it.ogt.kq.common.bm.utils.UniqueIDUtils;
import com.hyt.it.ogt.kq.service.bm.feign.tps.TpsClient;
import com.hyt.it.ogt.kq.service.bm.mapper.OrderBusinessFlowMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.OrderDetailMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.OrderMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.ProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentPayMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentSubjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentSubjectMidOrderDetailsMapper;
import com.hyt.it.ogt.kq.service.bm.model.dto.PayStudentSubjectDTO;
import com.hyt.it.ogt.kq.service.bm.model.entity.Order;
import com.hyt.it.ogt.kq.service.bm.model.entity.OrderBusinessFlow;
import com.hyt.it.ogt.kq.service.bm.model.entity.OrderDetail;
import com.hyt.it.ogt.kq.service.bm.model.entity.Project;
import com.hyt.it.ogt.kq.service.bm.model.entity.ProjectSubject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentInfo;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentPayInfo;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentProject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentSubject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentSubjectMidOrderDetails;
import com.hyt.it.ogt.kq.service.bm.model.vo.PayVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.StudentSubjectList;
import com.hyt.it.ogt.kq.service.bm.model.vo.SubjectPayRecordVO;
import com.hyt.it.ogt.kq.service.bm.service.IProjectSubjectService;
import com.hyt.it.ogt.kq.service.bm.service.stcenter.IStcenterStudentPayService;
import com.hyt.model.tps.vo.PayRequestGoodItem;
import com.hyt.model.tps.vo.PayRequestVo;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class IStcenterStudentPayServiceImpl extends BaseServiceImpl<StudentPayMapper, StudentInfo> implements IStcenterStudentPayService {

	@Resource
	private StudentPayMapper studentPayMapper;
	@Resource
	private ProjectMapper projectMapper;
	@Resource
	private OrderMapper orderMapper;
	@Resource
	private IProjectSubjectService iProjectSubjectService;
	@Resource
	TpsClient tpsClient;
	@Resource
	private StudentSubjectMapper studentSubjectMapper;
	@Resource
	private OrderBusinessFlowMapper orderBusinessFlowMapper;
	@Resource
	private OrderDetailMapper orderDetailMapper;
	@Resource
	private StudentSubjectMidOrderDetailsMapper studentSubjectMidOrderDetailsMapper;
	@Resource
	private StudentProjectMapper studentProjectMapper;

	@Lookup
	public PayRequestVo getPayBase() {
		return null;
	}


	/**
	 * @Params:
	 * @Description:	考生服务中心去支付，创建订单
	 * @Author: STARF
	 * @CreateDate: 2022/5/17 10:37
	 **/
	@Override
	public Map<String, Object> topay(PayVo payVo) {
		// 如果没有超时，对原有订单继续支付
		Map<String, Object> map = new HashMap<>();
		// 获取项目信息
		Project project = projectMapper.selectById(payVo.getProjectId());
		if(null == project) {
			map.put("msg", "报名项目不存在");
			return map;
		}
		if(null != project.getPayBeginTime() && LocalDateTime.now().isBefore(project.getPayBeginTime())) {
		    map.put("msg", "未到缴费开始时间");
            return map;
		}
		// 校验是否已经无法缴费
		if (null != project.getPayEndTime() && project.getPayEndTime().isBefore(LocalDateTime.now())) {
			map.put("msg", "报名项目已经超过缴费时间");
			return map;
		}
		// 获取考生需要支付的科目信息
		List<StudentSubject> studentSubjectList = getStudentPaySubjects(payVo);

		// 校验订单报考科目和目前报考科目是否一致
		List<String> stuSubIds = studentSubjectList.stream().map(StudentSubject::getId).distinct().collect(Collectors.toList());
		List<String> subjectIds = Arrays.asList(payVo.getSubjectIds().split(","));
		try {
			if (stuSubIds.containsAll(subjectIds) && subjectIds.containsAll(stuSubIds)) {
				Order latestUnPayOrder = orderMapper.queryLatestUnPayOrderByProjectIdAndRegId(payVo.getProjectId(), payVo.getRegId(),"0");
				// 如果查询不到订单，直接创建订单并去支付
				if (null == latestUnPayOrder) {
					return this.pay(payVo);
				}
				// 如果存在未支付订单， 判断是否已经超时
				Long minutes = ChronoUnit.MINUTES.between(latestUnPayOrder.getCreateDate(), LocalDateTime.now());
				boolean overTime = false;
				if (minutes > 1) {
					overTime = true;
				}
				// 如果已经超时，则创建新的订单
				if (overTime) {
					this.delOldOrder(payVo.getProjectId(), payVo.getRegId());
					//创建新订单
					return this.pay(payVo);
				}
				map.put("success", true);
				map.put("code", "0");
				map.put("obj", latestUnPayOrder.getOrderPayUrl());
				return map;
			} else {
				//不一致：废弃原订单，重新创建订单。逻辑删除原订单
				this.delOldOrder(payVo.getProjectId(), payVo.getRegId());
				//创建新订单
				return this.pay(payVo);
			}
		} catch (Exception e) {
			log.error("## pc pay create order error", e);
			map.put("msg", e.toString());
			return map;
		}
	}

//	/***
//	 * // 订单号，唯一(订单号规则：8位数自增长从10000001开始)
//	 * @return
//	 */
//	private String getOrderId() {
//		String orderId = orderMapper.getSequence() + "";// UUIDUtils.newSortUUID()
//		if (StringUtils.isEmpty(orderId)) {
//			orderId = "10000001";
//		}
//		return orderId;
//	}

	/****
	 * 获取考生需要支付的科目信息
	 * @param payVo
	 * @return
	 */
	private List<StudentSubject> getStudentPaySubjects(PayVo payVo) {
		List<StudentSubject> studentSubjectList = studentSubjectMapper.queryStudentSubject(null, "0", null, payVo.getStudentId(),null, payVo.getProjectId());
		// 查询项目的科目的信息
		List<ProjectSubject> projectSubjectList = iProjectSubjectService.querySubjectList(payVo.getProjectId(), null);
		// 过滤掉不是项目&&不需要缴费的科目信息
		Iterator<StudentSubject> iterator = studentSubjectList.iterator();
		while (iterator.hasNext()) {
			StudentSubject studentSubject = iterator.next();
			for (ProjectSubject projectSubject: projectSubjectList) {
				if (studentSubject.getSubjectId().equals(projectSubject.getSubjectId()) && projectSubject.getIsPay() == 0) {
					iterator.remove();
				}
			}
		}
		return studentSubjectList;
	}


	public StudentPayInfo queryPayInfo(String studentId) throws Exception {
		StudentPayInfo studentPayInfo = new StudentPayInfo();

		// 考生姓名、任务名称
		Map<String, String> map = studentPayMapper.getStudentName(studentId);
		String studentName = "";
		String projectName = "";
		String projectId = "";
		if (MapUtils.isNotEmpty(map)) {
			studentName = map.get("studentName");
			projectName = map.get("projectName");
			projectId = map.get("projectId");
		}
		studentPayInfo.setProjectId(projectId);
		studentPayInfo.setStudentName(studentName);
		studentPayInfo.setProjectName(projectName);

		Project project = projectMapper.selectById(projectId);
		if (null != project.getIsRefund() && project.getIsRefund() == 0) {
			if (null != project.getRefuseTime() && project.getRefuseTime().isAfter(LocalDateTime.now())) {
				studentPayInfo.setAllowRefund(1);
			}
		}
		studentPayInfo.setProjectAllowRefund(project.getIsRefund());
		// 项目需要审核
		String isVerify = null;
		if (null != project && BmProjectVerifyEnum.VERIFY.getVerifyStatus().equals(project.getIsVerify())) {
			isVerify = BmProjectVerifyEnum.VERIFY.getVerifyStatus().toString();
		}

		// 查询报名科目信息
		List<StudentSubjectList> list = studentPayMapper.getStuSubject(projectId, studentId, isVerify);

		// 考试科目拼接
		StringBuilder subjectNameString = new StringBuilder();
		// id集合
		StringBuilder idString = new StringBuilder();
		// 价格集合
		StringBuilder subjectPriceList = new StringBuilder();
		// 报名费用
		BigDecimal price = new BigDecimal("0.00");
		for (StudentSubjectList sList : list) {
			subjectNameString.append(sList.getSubjectName()).append(",");
			idString.append(sList.getId()).append(",");
			subjectPriceList.append(sList.getPrice()).append(",");
			price = price.add(sList.getPrice());
			studentPayInfo.setRegId(sList.getRegId());
			studentPayInfo.setStudentId(sList.getStudentId());
		}
		studentPayInfo.setSubjectPriceList(subjectPriceList.length() > 0 ? subjectPriceList.substring(0, subjectPriceList.length() - 1) : subjectPriceList.toString());
		studentPayInfo.setSubjectIds(idString.length() > 0 ? idString.substring(0, idString.length() - 1) : idString.toString());
		studentPayInfo.setPrice(price);
		studentPayInfo.setActrualPrice(price);
		studentPayInfo.setSubjectNames(subjectNameString.length() > 0 ? subjectNameString.substring(0, subjectNameString.length() - 1) : subjectNameString.toString());
		return studentPayInfo;
	}

	/**
	 * 去支付
	 */
	public Map<String, Object> pay(PayVo payVo) {
		// 项目信息
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			PayRequestVo payBase = getPayBase();
			// 获取项目信息
			Project project = projectMapper.selectById(payVo.getProjectId());
			// 校验是否已经无法缴费
			if (null != project.getPayEndTime() && project.getPayEndTime().isBefore(LocalDateTime.now())) {
				throw new Exception("报名项目已经超过缴费时间");
			}
			// 订单号，唯一(订单号规则：8位数自增长从10000001开始)
			String orderId = String.valueOf(System.nanoTime());
			payBase.setOfficeId(project.getOfficeId());
			payBase.setOrderId(orderId);
			// 订单金额的计算不能直接前端传，安全风险
			payBase.setOrderPrice(payVo.getActrualPrice().doubleValue());
			String notifyUrl = getPayNotifyUrl(project);
			payBase.setNotifyUrl(notifyUrl);
			if (payVo.getCallBackUrl().contains("localhost:9537")) {
				payBase.setCallBackUrl(payBase.getNotifyUrlDoman().replace("/ksbmApi", "") + payVo.getCallBackUrl().split("localhost:9537")[1]);
			} else {
				payBase.setCallBackUrl(payVo.getCallBackUrl());
			}
			String studentId = payVo.getStudentId();
			if(StrUtil.isNotBlank(studentId)) {
			   StudentProject studentProject = studentProjectMapper.selectById(studentId);
			   if(null != studentProject) {
			       payBase.setUserName(studentProject.getName());
			       payBase.setPhone(studentProject.getPhone());
			   }
			}
			// 构造商品类型
			List<ProjectSubject> payProjectSubjects = new ArrayList<>();
			PayStudentSubjectDTO payStudentSubjectDTO = getPayProjectSubject(payVo.getSubjectIds().split(","));
			if(null != payStudentSubjectDTO) {
				payProjectSubjects = payStudentSubjectDTO.getPayProjectSubjects();
			}
			List<PayRequestGoodItem> goods = consGoods(payProjectSubjects);
			payBase.setGoods(goods);
			String orderPayUrl = null;
			try {
				log.info("paypc.payBase=[{}]", FastJsonUtil.getBeanToJson(payBase));
				map = (Map<String, Object>) tpsClient.pay(payBase);
				log.info("paypc.map=[{}]", FastJsonUtil.getBeanToJson(map));
				Boolean success = Boolean.valueOf(String.valueOf(map.get("success")));
				String msg = String.valueOf(map.get("msg"));
				if (!success) {
					map.put("msg", msg);
					return map;
				}
				orderPayUrl = String.valueOf(map.get("obj"));
			} catch (Exception e) {
				log.info("tpsClient.pay 调用异常" , e);
				map.put("msg", "支付系统异常请稍后重试");
				return map;
			}
			this.createOrder(payVo, orderId, orderPayUrl, project.getOfficeId());
		} catch (Exception e) {
			log.error("pc pay create order error", e);
			map.put("msg", e.toString());
			return map;
		}
		return map;
	}

	/**
	 * @Params:
	 * @Description:	创建新订单
	 * @Author: STARF
	 * @CreateDate: 2022/5/17 16:33
	 **/
	public void createOrder(PayVo payVo, String orderId, String orderPayUrl, String officeId) {
		PayStudentSubjectDTO payStudentSubjectDTO = getPayProjectSubject(payVo.getSubjectIds().split(","));

		// 保存订单信息
		String projectId = payVo.getProjectId();
		String regId = payVo.getRegId();
		String studentId = getStudentIdByRegId(projectId, regId);
		Order entity = new Order();
		entity.setBmProjectId(projectId);
		entity.setId(orderId);
		String orderType = getOrderType(officeId);
		entity.setOrderPaySupplier(orderType);
		entity.setOrderType(orderType);
		entity.setOrderPrice(payVo.getActrualPrice().doubleValue());
		entity.setOrderTime(DateUtils.getNowTime("yyyy-MM-dd HH:mm:ss"));
		entity.setRegId(regId);
		entity.setPayStatus(BmPayStatusEnum.UNPAY.getPayStatus().toString());
		entity.setStudentId(studentId);
		entity.setCreateDate(LocalDateTime.now());
		entity.setUpdateDate(LocalDateTime.now());
		entity.setOrderPayUrl(orderPayUrl);
		entity.setDelFlag(Boolean.FALSE);
		orderMapper.insertOrder(entity);

		// 保存订单内容表信息
		Map<String, Object> orderDetails = new HashMap<String, Object>();
		String orderDetailsId = UUIDUtils.newSortUUID();
		orderDetails.put("id", orderDetailsId);
		orderDetails.put("bm_order_id", orderId);
		// 报名费用
		orderDetails.put("business_type", BmCostType.COST_BM.getType());
		orderDetails.put("actrual_price", payVo.getActrualPrice());
		orderDetails.put("order_price", payVo.getPrice());
		orderDetails.put("coupon_price", payVo.getCouponPrice());
		orderDetails.put("is_coupon", "");
		orderDetails.put("pay_type", "L");
		orderDetails.put("coupon_activity_id", payVo.getCouponActivityId()); // 优惠活动的id
		orderDetails.put("create_date", LocalDateTime.now());
		orderDetails.put("update_date", LocalDateTime.now());
		orderDetails.put("is_group", "0");
		orderMapper.insertOrderDetails(orderDetails);

		// 保存订单报名科目明细表
		String[] subjectStrings = payVo.getSubjectIds().split(",");
		Map<String, ProjectSubject> studentProjectSubjectMap = payStudentSubjectDTO.getStudentProjectSubjectMap();
		String[] subjectPrices = payVo.getSubjectPriceList().split(",");
		for (int i = 0; i < subjectStrings.length; i++) {
			Map<String, Object> subject = new HashMap<String, Object>();
			subject.put("id", UUIDUtils.newSortUUID());
			subject.put("bm_student_subject_id", subjectStrings[i]);
			subject.put("reg_id", payVo.getRegId());//
			ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
			if (null != projectSubject && null != projectSubject.getPrice()) {
				subject.put("pay_subject_price", String.valueOf(projectSubject.getPrice()));
			} else {
				subject.put("pay_subject_price", subjectPrices[i]);
			}
			subject.put("bm_order_details_id", orderDetailsId);
			// 缴费中
			subject.put("bm_pay_status", BmMidOrderPayStatus.PAY_PEDDING.getPayStatus());
			subject.put("create_date", LocalDateTime.now());
			subject.put("update_date", LocalDateTime.now());
			subject.put("student_id", payVo.getStudentId());
			orderMapper.insertOrderSubject(subject);
		}
		// 记录支付流水
		for (int i = 0; i < subjectStrings.length; i++) {
			ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
			OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
			Long businessFlowId = UniqueIDUtils.generateId();
			orderBusinessFlow.setId(businessFlowId);
			orderBusinessFlow.setBmOrderId(entity.getId());
			orderBusinessFlow.setBmOrderDetailId(orderDetailsId);
			orderBusinessFlow.setBusinessType(BmCostType.COST_BM.getType());
			// 流水的状态为待支付
			orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
			if(null != projectSubject && null != projectSubject.getPrice()) {
				orderBusinessFlow.setOrderPrice(Double.valueOf(String.valueOf(projectSubject.getPrice())));
			}
			orderBusinessFlow.setOrderPaySupplier(entity.getOrderPaySupplier());
			orderBusinessFlow.setOrderType(entity.getOrderType());
			orderBusinessFlow.setBmProjectId(entity.getBmProjectId());
			orderBusinessFlow.setRegId(payVo.getRegId());
			orderBusinessFlow.setBmStudentSubjectId(subjectStrings[i]);
			orderBusinessFlow.setStudentId(payVo.getStudentId());
			orderBusinessFlow.setCreateDate(LocalDateTime.now());
			orderBusinessFlow.setUpdateDate(LocalDateTime.now());
			orderBusinessFlow.setDelFlag(Boolean.FALSE);
			orderBusinessFlowMapper.insert(orderBusinessFlow);
		}
	}

	/**
     * 通过用户ID获取考生ID
     * @param projectId
     * @param regId
     * @return
     */
    private String getStudentIdByRegId(String projectId, String regId) {
        StudentProject studentProject = studentProjectMapper.getProjectStudent(projectId, regId);
        if(null != studentProject) {
            return studentProject.getId();
        }
        return null;
    }


    private String getOrderType(String officeId) {
		String payProvider = PayProviderType.YIBAO.getType();
		try {
			log.info("## getOrderType officeId:{}", officeId);
			payProvider = tpsClient.getPayProvider(officeId);
			log.info("## getOrderType officeId:{}", payProvider);
		} catch (Exception e) {
			logger.error("## getOrderType error", e);
		}
		if(PayProviderType.SHOUYIXIN.getType().equals(payProvider)) {
			return "SHOU_YI_XIN";
		}
		if(PayProviderType.YIBAO.getType().equals(payProvider)) {
			return "YIBAO";
		}
		if(PayProviderType.NANCHANGFEISHUI.getType().equals(payProvider)) {
            return "NANCHANGFEISHUI";
        }
		return "WEIZHI";
	}


	/**
	 * @Params:
	 * @Description:	删除旧订单
	 * @Author: STARF
	 * @CreateDate: 2022/5/17 16:11
	 **/
	public void delOldOrder(String projectId, String regId) {
		QueryWrapper<Order> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(Order::getPayStatus, "0").eq(Order::getDelFlag, false).eq(Order::getBmProjectId, projectId).eq(Order::getRegId, regId);
		List<Order> oldOrderList = orderMapper.selectList(wrapper);
		for (Order order: oldOrderList) {
			QueryWrapper<OrderDetail> detailWrapper = new QueryWrapper<>();
			detailWrapper.lambda().eq(OrderDetail::getBmOrderId, order.getId());
			List<OrderDetail> oldDetailList = orderDetailMapper.selectList(detailWrapper);
			for (OrderDetail detail: oldDetailList) {
				StudentSubjectMidOrderDetails ssmod = new StudentSubjectMidOrderDetails();
				ssmod.setDelFlag(true);
				UpdateWrapper<StudentSubjectMidOrderDetails> ssmodWrapper = new UpdateWrapper<>();
				ssmodWrapper.lambda().eq(StudentSubjectMidOrderDetails::getBmOrderDetailsId, detail.getId());
				studentSubjectMidOrderDetailsMapper.update(ssmod, ssmodWrapper);
				detail.setDelFlag(true);
				orderDetailMapper.updateById(detail);
			}
			order.setDelFlag(true);
			orderMapper.updateById(order);
		}
	}

	/***
	 * 计算订单的实际支付金额
	 * @param subjectIdsStr
	 * @param actrualPrice
	 * @return
	 */
	public Double getOrderPayActrualPrice(String subjectIdsStr, BigDecimal actrualPrice) {
		if(StringUtils.isEmpty(subjectIdsStr)) {
			return Double.valueOf("0");
		}
		String[] subjectIds = subjectIdsStr.split(",");
		// 构造商品类型
		List<ProjectSubject> payProjectSubjects = new ArrayList<>();
		PayStudentSubjectDTO payStudentSubjectDTO = getPayProjectSubject(subjectIds);
		if(null != payStudentSubjectDTO) {
			payProjectSubjects = payStudentSubjectDTO.getPayProjectSubjects();
		}
		// 报名费用
		BigDecimal price = new BigDecimal("0.00");
		if(CollectionUtils.isNotEmpty(payProjectSubjects)) {
			for (ProjectSubject projectSubject : payProjectSubjects) {
				price = price.add(projectSubject.getPrice());
			}
		}
		return Double.valueOf(String.valueOf(price));
	}

	/***
	 * 获取支付配置的异步回调url
	 * @param project
	 * @return
	 */
	private String getPayNotifyUrl(Project project) {
		PayRequestVo payBase = getPayBase();
		String callbackUrl;
		String officeId = project.getOfficeId();
		StringBuilder callbackUrlSb = new StringBuilder();
		if (StringUtils.isEmpty(payBase.getNotifyUrlDoman())) {
			callbackUrlSb.append("http://");
			callbackUrlSb.append(payBase.getIp());
			callbackUrlSb.append(":");
			callbackUrlSb.append(payBase.getPort());
			String payProvider = PayProviderType.YIBAO.getType();
			try {
				payProvider = tpsClient.getPayProvider(officeId);
			} catch (Exception e) {
				logger.error("## getPayProvider error", e);
			}
			if(PayProviderType.SHOUYIXIN.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/notifyUrl?officeId=");
			}
			if(PayProviderType.YIBAO.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/yopnotifyUrl?officeId=");
			}
			if(PayProviderType.NANCHANGFEISHUI.getType().equals(payProvider)) {
                callbackUrlSb.append("/bm/studentPay/ncNonTaxPayNotifyUrl?officeId=");
            }
			callbackUrlSb.append(project.getOfficeId());
			callbackUrl = callbackUrlSb.toString();
		} else {
			callbackUrlSb.append(payBase.getNotifyUrlDoman());
			String payProvider = PayProviderType.YIBAO.getType();
			try {
				payProvider = tpsClient.getPayProvider(officeId);
			} catch (Exception e) {
				logger.error("## getPayProvider error", e);
			}
			if(PayProviderType.SHOUYIXIN.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/notifyUrl?officeId=");
			}
			if(PayProviderType.YIBAO.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/yopnotifyUrl?officeId=");
			}
			if(PayProviderType.NANCHANGFEISHUI.getType().equals(payProvider)) {
                callbackUrlSb.append("/bm/studentPay/ncNonTaxPayNotifyUrl?officeId=");
            }
			callbackUrlSb.append(project.getOfficeId());
			callbackUrl = callbackUrlSb.toString();
		}
		return callbackUrl;
	}

	/***
	 * 构建订单商品信息
	 * @param payProjectSubjects
	 * @return
	 */
	private List<PayRequestGoodItem> consGoods(List<ProjectSubject> payProjectSubjects) {
		List<PayRequestGoodItem> goods = new ArrayList<PayRequestGoodItem>();
		if(CollectionUtils.isEmpty(payProjectSubjects)) {
			return goods;
		}
		for (ProjectSubject projectSubject : payProjectSubjects) {
			PayRequestGoodItem payRequestGoodItem = new PayRequestGoodItem();
			payRequestGoodItem.setName(projectSubject.getSubjectName());
			payRequestGoodItem.setDescription(projectSubject.getSubjectName());
			payRequestGoodItem.setAmount(Double.valueOf(String.valueOf(projectSubject.getPrice())));
			payRequestGoodItem.setReceiver(projectSubject.getRemark());
			goods.add(payRequestGoodItem);
		}
		return goods;
	}

	/**
	 *获取缴费的报名项目
	 * @param subjectArry
	 * @return
	 */
	private PayStudentSubjectDTO getPayProjectSubject(String[] subjectArry) {
		PayStudentSubjectDTO payStudentSubjectDTO = new PayStudentSubjectDTO();
		List<ProjectSubject> bmProjectSubjects = new ArrayList<>();
		List<StudentSubject> bmStudentSubjects = new ArrayList<>();
		Map<String, ProjectSubject> studentProjectSubjectMap = new HashMap<>();
		if(null == subjectArry || subjectArry.length ==0 ) {
			return null;
		}
		
		for (String studentSubjectId : subjectArry) {
			StudentSubject studentSubject = studentSubjectMapper.getStudentSubjectById(studentSubjectId);
			if(null != studentSubject &&  BmSubjectNeedPayEnum.PAY.getPayStatus().equals(studentSubject.getIsPay()) && !Integer.valueOf(1).equals(studentSubject.getPay())) {
				ProjectSubject projectSubject = iProjectSubjectService.queryBySubjectId(studentSubject.getProjectId(), studentSubject.getSubjectId());
				if(null != projectSubject && BmProjectNeedPayEnum.PAY.getPayStatus().equals(projectSubject.getIsPay())) {
					bmStudentSubjects.add(studentSubject);
					bmProjectSubjects.add(projectSubject);
					studentProjectSubjectMap.put(studentSubjectId, projectSubject);
				}
			}
		}
		payStudentSubjectDTO.setPayProjectSubjects(bmProjectSubjects);
		payStudentSubjectDTO.setStudentSubject(bmStudentSubjects);
		payStudentSubjectDTO.setStudentProjectSubjectMap(studentProjectSubjectMap);
		return payStudentSubjectDTO;
	}

	/**
	 * @Params:
	 * @Description:	缴费栏查询订单列表
	 * @Author: STARF
	 * @CreateDate: 2022/5/17 16:56
	 **/
	@Override
	public StudentPayInfo getStudentPayInfo(String studentId) throws Exception {
		StudentPayInfo studentPayInfo = this.queryPayInfo(studentId);

		List<StudentSubject> studentSubjectList = studentSubjectMapper.getStudentSbjects(studentPayInfo.getProjectId(), studentId);
		List<ProjectSubject> subjectList = iProjectSubjectService.querySubjectList(studentPayInfo.getProjectId(), null);

		List<StudentSubject> list = new ArrayList<>();
		int allowRefund = 0;
		for (StudentSubject studentSubject: studentSubjectList) {
			for (ProjectSubject projectSubject: subjectList) {
			    // 如果科目不需要缴费
				if (null != projectSubject.getIsPay() && projectSubject.getIsPay() == 0) {
					continue;
				}
				if (studentSubject.getSubjectId().equals(projectSubject.getSubjectId())) {
					if (null != studentSubject.getIsPay() && 0 != studentSubject.getIsPay() && null == studentSubject.getBmTime()) {
						studentSubject.setBmTime(studentSubject.getUpdateDate());
					}
					studentSubject.setPrice(null != projectSubject.getPrice() ? projectSubject.getPrice().doubleValue() : null);
					studentSubject.setIsPay(projectSubject.getIsPay());
					// 科目需要缴费
					if (projectSubject.getIsPay() == 1) {
						studentSubject.setPayStatus(studentSubject.getPay() + "");
						if (studentSubject.getPay() == 1) {
							allowRefund = 1;
						}
					} else {
					    // 如果科目不需要缴费则默认已缴费
						studentSubject.setPayStatus("1");
					}
					list.add(studentSubject);
				}
			}
		}

		if (studentPayInfo.getAllowRefund() == 1) {
			studentPayInfo.setAllowRefund(allowRefund);
		}
		studentPayInfo.setStudentSubjectList(list);
		return studentPayInfo;
	}


	/**
	 * @Params:
	 * @Description:	考生科目的缴退费记录
	 * @Author: STARF
	 * @CreateDate: 2022/5/27 9:18
	 **/
	@Override
	public List<SubjectPayRecordVO> querystudentSubjectPayRecord(String studentId, String subjectId) {
		List<SubjectPayRecordVO> list = orderBusinessFlowMapper.querySubjectPayRecord(studentId, subjectId);
		list.removeIf(vo -> BmPayBusinessFlowType.PAY_FAIL.getBusinessType().equals(vo.getBusinessStatus()) 
		                 || BmPayBusinessFlowType.PAY_WAITTING.getBusinessType().equals(vo.getBusinessStatus()));
		return list;
	}

	/**
     * @Params:
     * @Description:    考生科目的缴退费记录
     * @Author: STARF
     * @CreateDate: 2022/5/27 9:18
     **/
    @Override
    public Boolean querystudentSubjectPayRecord(String studentId, String subjectId, String projectId) {
        
        StudentSubject studentSubject = studentSubjectMapper.getStudentSbject(studentId, subjectId, projectId);
        if(null != studentSubject && BmPayStatusEnum.PAY.getPayStatus().equals(studentSubject.getPay())) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;

    }
    
	/**
	 * @Params:
	 * @Description:	判断订单是否超时
	 * @Author: STARF
	 * @CreateDate: 2022/6/8 15:42
	 **/
	@Override
	public boolean orderHasOverTime(String studentId, String subjectId) {
		StudentProject studentProject = studentProjectMapper.selectById(studentId);
		//获取所有待支付科目的订单
		List<StudentSubject> studentSubjectList = studentSubjectMapper.queryStudentSubject(null, "0", null, studentId,null, studentProject.getProjectId());
		List<ProjectSubject> projectSubjectList = iProjectSubjectService.querySubjectList(studentProject.getProjectId(), null);
		Iterator<StudentSubject> iterator = studentSubjectList.iterator();
		while (iterator.hasNext()) {
			StudentSubject studentSubject = iterator.next();
			for (ProjectSubject projectSubject: projectSubjectList) {
				if (studentSubject.getSubjectId().equals(projectSubject.getSubjectId()) && projectSubject.getIsPay() == 0) {
					iterator.remove();
				}
			}
		}

		// 校验订单报考科目和目前报考科目是否一致
		List<String> stuSubIds = new ArrayList<>();
		studentSubjectList.forEach(studentSubject ->  stuSubIds.add(studentSubject.getId()));
		List<String> subjectIds = Arrays.asList(subjectId.split(","));
		boolean overTime = false;
		if (stuSubIds.containsAll(subjectIds) && subjectIds.containsAll(stuSubIds)) {
			QueryWrapper<Order> wrapper = new QueryWrapper<>();
			wrapper.lambda().eq(Order::getPayStatus, "0").eq(Order::getDelFlag, false)
					.eq(Order::getBmProjectId, studentProject.getProjectId()).eq(Order::getRegId, studentProject.getRegId());
			List<Order> oldOrderList = orderMapper.selectList(wrapper);

			// 超时：重新创建订单，逻辑删除超时订单 超时的定义目前定义是五分钟
			for (Order order : oldOrderList) {
				Long minutes = ChronoUnit.MINUTES.between(order.getCreateDate(), LocalDateTime.now());
				if (minutes > 5) {
					overTime = true;
					break;
				}
			}
		} else {
			overTime = true;
		}
		return overTime;
	}

    /**
     * @Params:
     * @Description: 考生报名科目是否需要缴费
     * @Author: STARF
     * @CreateDate: 2022/6/10 10:03
     **/
    @Override
    public boolean studentProjectNeedPay(String studentId) {
        QueryWrapper<StudentSubject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(StudentSubject::getStudentId, studentId);
        List<StudentSubject> list = studentSubjectMapper.selectList(wrapper);

        for (StudentSubject s : list) {
            // 待审核的不允许进入缴费页面
            StudentProject studentProject = studentProjectMapper.selectById(s.getStudentId());
            if(null == studentProject) {
                continue;
            }
            if (null != studentProject && null != studentProject.getIsAudit() && 1 != studentProject.getIsAudit()) {
                Project project = projectMapper.selectById(studentProject.getProjectId());
                if (null != project && null != project.getIsVerify() && 1 == project.getIsVerify()) {
                    return false;
                }
            }
            ProjectSubject projectSubject = iProjectSubjectService.queryBySubjectId(studentProject.getProjectId(), s.getSubjectId());
            if (null != projectSubject.getIsPay() && projectSubject.getIsPay() == 1) {
                return true;
            }
        }
        return false;
    }

}
